package com.yunyao.framework.audit;

import com.yunyao.common.constant.enums.AuditStatusEnums;
import com.yunyao.common.constant.enums.BindContractStatusEnums;
import com.yunyao.common.constant.enums.SaleContractType;
import com.yunyao.common.core.BaseContext;
import com.yunyao.common.core.UserInfoRequest;
import com.yunyao.common.dto.audit.AuditFlowTypeEnums;
import com.yunyao.common.dto.audit.AuditResultEnums;
import com.yunyao.common.dto.audit.CreateAuditFlowDto;
import com.yunyao.common.exception.AuditException;
import com.yunyao.common.exception.BusinessException;
import com.yunyao.common.utils.RandomUtils;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.dao.model.*;
import com.yunyao.dao.service.bamu.*;
import com.yunyao.framework.dto.sale.SaleContractApprovalDto;
import com.yunyao.framework.service.systemtwo.ContractService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;

import static com.yunyao.common.constant.Constants.MINUS;
import static com.yunyao.common.constant.Constants.PURCHASE_CODE_PREFIX_SHORT;
import static com.yunyao.common.constant.Constants.SALE_CODE_PREFIX_SHORT;

/**
 * @author xingjishuai
 * @date 2024-08-01
 */
@Slf4j
@Component
public class SaleContractAuditHandle extends AbstractAuditFlowHandle {
    @Autowired
    private IBamuPurchaseContractService iBamuPurchaseContractService;
    @Autowired
    private IBamuContractMaterialService iBamuContractMaterialService;
    @Autowired
    private IBamuContractWirePayService iBamuContractWirePayService;
    @Autowired
    private IBamuContractNodePayService iBamuContractNodePayService;
    @Autowired
    private IBamuSaleContractService ibamuSaleContractService;
    @Resource
    private IBamuPurchaseContractPrePaymentService purchaseContractPrePaymentService;
    @Resource
    private ContractService contractService;

    /**
     * 提交销售合同审批流程。
     *
     * @param bizId 业务ID，用于查询特定的销售合同。
     * @throws AuditException 当审批流程创建或更新过程中出现异常时抛出。
     */
    @Transactional(rollbackFor = AuditException.class)
    public void submit(String bizId) throws AuditException {
        // 根据业务ID获取销售合同信息，不包括已删除的记录。
        BamuSaleContract bamuSaleContract = ibamuSaleContractService.getByIdNoDelete(bizId);
        // 获取合同名称，用于审批流程创建时的识别。
        String contractName = bamuSaleContract.getContractName();
        // 获取合同状态，用于审批流程创建时的参数。
        Integer status = bamuSaleContract.getStatus();
        // 从默认审批模型信息中获取销售合同模型ID。
        String saleContractModelId = defaultAuditModelInfo.getSaleContractId();
        try {
            // 检查提交的数据是否符合要求。
            checkSubmitData(bamuSaleContract);
            // 创建审批流程实例，并传入必要的参数。
            CreateAuditFlowDto createAuditFlowDto = creatFlow(saleContractModelId,
                    AuditFlowTypeEnums.MODEL_NAME_SALE_CONTRACT.getType(), bizId, contractName,
                    String.valueOf(status));
            // 将审批流程的相关信息更新到销售合同记录中。
            bamuSaleContract.setProcessInstanceId(createAuditFlowDto.getProcessInstanceId());
            bamuSaleContract.setDeploymentId(createAuditFlowDto.getDeploymentId());
            bamuSaleContract.setModelSchemeInfoId(createAuditFlowDto.getModelSchemeInfoId());
            bamuSaleContract.setProcessVersion(createAuditFlowDto.getProcessVersion());
            // 更新销售合同的审批状态为“审批中”。
            bamuSaleContract.setAuditStatus(String.valueOf(AuditStatusEnums.AUDIT.getType()));
            // 更新销售合同信息。
            ibamuSaleContractService.updateById(bamuSaleContract);

        } catch (Exception e) {
            // 记录审批流程提交过程中的异常。
            log.error("销售合同submit approval error", e);
            // 抛出自定义异常，提示审批流程提交失败。
            throw new AuditException(e.getMessage());
        }
    }

    /**
     * 销售合同预付款表
     *
     * @param bamuSaleContract
     * @param contractType
     */
    private void addContractPrePayment(BamuSaleContract bamuSaleContract, @NotBlank String contractType) {
            BamuContractNodePay nodePay = contractService.findByContractIdStatus(bamuSaleContract.getId(), "0");
            if (nodePay == null) {
                log.error("根据合同ID没有找到对应的付款节点信息,合同ID:{},节点类型:{}", bamuSaleContract.getId(), 0);
                return;
            }
            UserInfoRequest userInfo = BaseContext.getUserInfo();
            BamuPurchaseContractPrePayment dto = new BamuPurchaseContractPrePayment();
            dto.setContractId(bamuSaleContract.getId());
            dto.setContractNo(bamuSaleContract.getContractNo());
            dto.setContractName(bamuSaleContract.getContractName());
            dto.setContractType(contractType);
            dto.setProjectId(bamuSaleContract.getProjectId());
            dto.setProjectName(bamuSaleContract.getProjectName());
            dto.setProjectDeptId(bamuSaleContract.getProjectDeptId());
            dto.setProjectDeptName(bamuSaleContract.getProjectDeptName());
            dto.setProjectAddress(bamuSaleContract.getProjectAddress());
            dto.setSupplierDeptId(bamuSaleContract.getSupplierDeptId());
            dto.setSupplierDeptName(bamuSaleContract.getSupplierDeptName());
            dto.setSupplierCategoryId(bamuSaleContract.getSupplierCategoryId());
            dto.setSupplierCategoryName(bamuSaleContract.getSupplierCategoryName());
            dto.setSupplierCategoryName(bamuSaleContract.getSupplierCategoryName());

            dto.setContractPrePaymentRate(nodePay.getBackPayRate());
            dto.setContractPrePaymentDay(nodePay.getNatureDay());
            //数据库为null 0  暂且为0
            dto.setContractPrePaymentDayType(0);
            //合同预收款金额
            dto.setContractPrePaymentPrice(bamuSaleContract.getContractTotalPrice().multiply(nodePay.getBackPayRate()));
            //todo 暂时给最新日期
            dto.setContractPrePaymentDate(new Date());
            //真实付款金额
            dto.setContractRealPaymentPrice(bamuSaleContract.getContractTotalRealPrice());
            dto.setContractNum(bamuSaleContract.getContractNum());
            dto.setContractTotalPrice(bamuSaleContract.getContractTotalPrice());
            dto.setContractTotalRealPrice(bamuSaleContract.getContractTotalRealPrice());
            //合同汇款总金额-可能存在误差
            dto.setContractBackPrice(bamuSaleContract.getContractTotalPrice());
            //结算单文件
            dto.setReconciliationSettlementFile(bamuSaleContract.getContractFile());
            //对账结算说明
            dto.setReconciliationSettlementMark(bamuSaleContract.getMark());
            dto.setCreatedAt(new Date());
            dto.setCreatedBy(userInfo.getRealName());
            dto.setCreateDept(userInfo.getDeptId());
            dto.setStatus(1);
            dto.setTenantId(bamuSaleContract.getTenantId());
            dto.setAuditStatus(bamuSaleContract.getAuditStatus());
            dto.setProcessInstanceId(bamuSaleContract.getProcessInstanceId());
            dto.setModelSchemeInfoId(bamuSaleContract.getModelSchemeInfoId());
            dto.setDeploymentId(bamuSaleContract.getDeploymentId());
            dto.setProcessVersion(bamuSaleContract.getProcessVersion());
            //付款方式
            dto.setPaymentMethod(null);
            dto.setContractMethod(bamuSaleContract.getContractMethod());
            dto.setPurchaseDeptId(bamuSaleContract.getPurchaseDeptId());
            dto.setPurchaseDeptName(bamuSaleContract.getPurchaseDeptName());
            dto.setCheckMark(bamuSaleContract.getMark());
            dto.setCheckFile(bamuSaleContract.getContractFile());
            //开票状态
            dto.setReceiptStatus("0");
            //回款金额
            dto.setReceivePrice(BigDecimal.ZERO);
            //结余金额
            dto.setBalanceAmount(BigDecimal.ZERO);
            purchaseContractPrePaymentService.add(dto);
            log.info("销售合同预付款表生成成功！");
    }

    /**
     * 审批销售合同
     * 该方法负责对销售合同进行审批，根据审批结果更新合同状态，并触发后续流程
     *
     * @param approvalDto 包含审批信息的数据传输对象
     * @throws AuditException 审批过程中发生异常时抛出
     */
    @Transactional(rollbackFor = Exception.class)
    public void approval(SaleContractApprovalDto approvalDto) throws AuditException {
        try {
            // 获取业务ID
            String bizId = approvalDto.getId();
            // 获取审批结果
            Boolean auditResult = approvalDto.getAuditResult();
            // 根据审批结果转换为字符串表示
            String auditResultStr = auditResult ? AuditResultEnums.AGREE.getKey() :
                    AuditResultEnums.REJECT.getKey();
            // 通过业务ID获取销售合同信息，注意此处未删除记录
            BamuSaleContract bamuSaleContract = ibamuSaleContractService.getByIdNoDelete(bizId);
            // 检查审批数据是否符合要求
            checkApprovalData(bamuSaleContract);
            // 执行流程，并获取是否结束的标志
            boolean isEnd = executeFlow(bamuSaleContract.getProcessInstanceId(),
                    bamuSaleContract.getDeploymentId(), auditResultStr,
                    approvalDto.getAuditResultMsg(), approvalDto.getAuditFileList());
            // 如果流程未结束，则直接返回
            if (!isEnd) {
                return;
            }
            // 根据审批结果更新合同状态
            if (auditResult) {
                // 审批通过的情况下，更新为审批成功状态
                bamuSaleContract.setAuditStatus(String.valueOf(AuditStatusEnums.AUDIT_SUCCESS.getType()));
                // 创建采购合同，作为审批通过后的后续操作
                createPurchaseContract(bamuSaleContract);
                // 更新为已绑定状态
                bamuSaleContract.setBindContractStatus(String.valueOf(BindContractStatusEnums.YES.getType()));
                //生成销售预付款
                addContractPrePayment(bamuSaleContract, "0");

            } else {
                // 审批未通过的情况下，更新为审批拒绝状态
                bamuSaleContract.setAuditStatus(String.valueOf(AuditStatusEnums.AUDIT_REJECT.getType()));
            }
            // 更新销售合同信息
            ibamuSaleContractService.updateById(bamuSaleContract);
            // 更新销售合同信息。
            ibamuSaleContractService.updateById(bamuSaleContract);
        } catch (Exception e) {
            // 记录审批过程中的异常信息
            log.error("销售合同 approval error", e);
            // 将异常信息包装后抛出
            throw new AuditException(e.getMessage());
        }

    }


    /**
     * 创建采购合同
     * 根据销售合同信息生成采购合同信息，实现从销售到采购的转换
     * 该方法详细解释了为什么需要从销售合同生成采购合同，以及如何处理相关信息
     *
     * @param bamuSaleContract 销售合同对象，包含销售合同的详细信息
     */
    private void createPurchaseContract(BamuSaleContract bamuSaleContract) {
        try {
            // 获取销售合同的ID，用于后续查询和转换
            String id = bamuSaleContract.getId();

            // 将销售合同信息转换为采购合同信息
            BamuPurchaseContract bamuPurchaseContract =
                    saleToPurchaseContractInfo(bamuSaleContract);

            // 获取与销售合同关联的电汇支付信息，并将其转换为采购合同的电汇支付信息
            BamuContractWirePay contractWirePay = iBamuContractWirePayService.getByContractId(id);
            saleToPurchaseContractWirePayInfo(bamuPurchaseContract, contractWirePay);

            // 获取销售合同的所有节点支付信息，并将其转换为采购合同的节点支付信息列表
            List<BamuContractNodePay> contractNodePayList =
                    iBamuContractNodePayService.listByContractId(id);
            saleToPurchaseContractNodePayList(bamuPurchaseContract, contractNodePayList);

            // 获取销售合同的所有材料信息，并将其转换为采购合同的材料信息列表
            List<BamuContractMaterial> contractMaterialList =
                    iBamuContractMaterialService.listByContractId(id);
            saleToPurchaseContractMaterialList(bamuPurchaseContract, contractMaterialList);
            iBamuPurchaseContractService.updateById(bamuPurchaseContract);
        } catch (Exception var) {
            // 记录异常信息，以便于问题追踪和处理
            log.error("销售审核成功 创建采购合同 失败", var);
        }
    }

    /**
     * 将销售合同材料列表转换为采购合同材料列表并保存
     *
     * @param bamuPurchaseContract 采购合同实体，用于关联材料信息所属的合同
     * @param contractMaterialList 销售合同材料列表，包含需要转换并保存的材料信息
     */
    private void saleToPurchaseContractMaterialList(BamuPurchaseContract bamuPurchaseContract,
                                                    List<BamuContractMaterial> contractMaterialList) {
        // 检查材料列表是否为空，为空则直接返回，不进行后续操作
        if (CollectionUtils.isEmpty(contractMaterialList)) {
            return;
        }
        // 创建一个新的列表，用于存储转换后的采购合同材料信息
        List<BamuContractMaterial> list = Lists.newArrayList();

        // 遍历销售合同材料列表，逐个材料进行转换
        for (BamuContractMaterial contractMaterial : contractMaterialList) {
            // 创建一个新的采购合同材料实体
            BamuContractMaterial bamuContractMaterial = new BamuContractMaterial();
            // 设置采购合同ID
            bamuContractMaterial.setContractId(bamuPurchaseContract.getId());
            // 以下多行代码将销售合同材料信息复制到采购合同材料实体中
            bamuContractMaterial.setMaterialId(contractMaterial.getMaterialId());
            bamuContractMaterial.setMaterialCode(contractMaterial.getMaterialCode());
            bamuContractMaterial.setMaterialTexture(contractMaterial.getMaterialTexture());
            bamuContractMaterial.setMaterialName(contractMaterial.getMaterialName());
            bamuContractMaterial.setMaterialSpecs(contractMaterial.getMaterialSpecs());
            bamuContractMaterial.setMaterialModel(contractMaterial.getMaterialModel());
            bamuContractMaterial.setMaterialUnit(contractMaterial.getMaterialUnit());
            bamuContractMaterial.setMaterialBrand(contractMaterial.getMaterialBrand());
            bamuContractMaterial.setMaterialNum(contractMaterial.getMaterialNum());
            bamuContractMaterial.setMaterialTaxCode(contractMaterial.getMaterialTaxCode());
            bamuContractMaterial.setMaterialTaxShortName(contractMaterial.getMaterialTaxShortName());
            bamuContractMaterial.setTenantId(contractMaterial.getTenantId());
            bamuContractMaterial.setMaterialMark(contractMaterial.getMaterialMark());
            bamuContractMaterial.setIsAdd(contractMaterial.getIsAdd());
            bamuContractMaterial.setNameIsSame(contractMaterial.getNameIsSame());
            bamuContractMaterial.setSpecsIsSame(contractMaterial.getSpecsIsSame());
            bamuContractMaterial.setModelIsSame(contractMaterial.getModelIsSame());
            bamuContractMaterial.setUnitIsSame(contractMaterial.getUnitIsSame());
            bamuContractMaterial.setMaterialSortNum(contractMaterial.getMaterialSortNum());
            bamuContractMaterial.setContractMaterialId(contractMaterial.getId());
            bamuContractMaterial.setIsCopy(contractMaterial.getIsCopy());
            bamuContractMaterial.setApplyNum(contractMaterial.getApplyNum());
            bamuContractMaterial.setCheckNum(contractMaterial.getCheckNum());
            bamuContractMaterial.setSaleContractExcludingTaxUnitPrice(contractMaterial.getExcludingTaxUnitPrice());
            bamuContractMaterial.setTax(contractMaterial.getTax());
            bamuContractMaterial.setIncludingTaxTotalPrice(contractMaterial.getIncludingTaxTotalPrice());
            bamuContractMaterial.setIncludingTaxUnitPrice(contractMaterial.getIncludingTaxUnitPrice());
            bamuContractMaterial.setExcludingTaxUnitPrice(contractMaterial.getExcludingTaxUnitPrice());
            // 将转换后的采购合同材料实体添加到列表中
            list.add(bamuContractMaterial);
        }
        // 批量保存转换后的采购合同材料信息，设置批处理数量为50
        iBamuContractMaterialService.saveBatch(list, 50);
    }


    /**
     * 将销售合同的支付条款列表转换并保存为采购合同的支付条款列表
     *
     * @param bamuPurchaseContract 采购合同对象，用于关联支付条款
     * @param contractNodePayList  销售合同的支付条款列表，用于转换
     */
    private void saleToPurchaseContractNodePayList(BamuPurchaseContract bamuPurchaseContract,
                                                   List<BamuContractNodePay> contractNodePayList) {
        // 检查支付条款列表是否为空，如果为空则直接返回，不进行后续操作
        if (CollectionUtils.isEmpty(contractNodePayList)) {
            return;
        }
        // 创建一个新的BamuContractNodePay对象列表，用于存储转换后的采购合同支付条款
        ArrayList<BamuContractNodePay> list = Lists.newArrayList();
        // 遍历销售合同的支付条款列表，逐个转换为采购合同的支付条款
        for (BamuContractNodePay contractNodePay : contractNodePayList) {
            BamuContractNodePay purchaseContractNodePay = new BamuContractNodePay();
            // 设置采购合同支付条款的各项属性，使其与销售合同的相应条款一致
            purchaseContractNodePay.setContractId(bamuPurchaseContract.getId());
            purchaseContractNodePay.setNodeType(contractNodePay.getNodeType());
            purchaseContractNodePay.setNodeTypeName(contractNodePay.getNodeTypeName());
            purchaseContractNodePay.setNodeTriggerType(contractNodePay.getNodeTriggerType());
            purchaseContractNodePay.setNodeTriggerTypeName(contractNodePay.getNodeTriggerTypeName());
            purchaseContractNodePay.setAutoStatus(contractNodePay.getAutoStatus());
            purchaseContractNodePay.setMonthDay(contractNodePay.getMonthDay());
            purchaseContractNodePay.setNatureDay(contractNodePay.getNatureDay());
            purchaseContractNodePay.setBackPayRate(contractNodePay.getBackPayRate());
            purchaseContractNodePay.setNodeMark(contractNodePay.getNodeMark());
            purchaseContractNodePay.setStatus(contractNodePay.getStatus());
            purchaseContractNodePay.setTenantId(contractNodePay.getTenantId());
            // 将转换后的采购合同支付条款添加到列表中
            list.add(purchaseContractNodePay);
        }
        // 批量保存转换后的采购合同支付条款列表
        iBamuContractNodePayService.saveBatch(list, 100);
    }

    /**
     * 将销售合同的汇款信息关联到采购合同中
     *
     * @param bamuPurchaseContract 采购合同对象，包含采购合同的详细信息
     * @param contractWirePay      汇款信息对象，包含汇款相关的详细信息
     *                             <p>
     *                             说明：此方法用于将特定的汇款信息（如价格类型、基数价格、增长价格等）
     *                             关联到一个采购合同中，为采购合同提供汇款相关的详细信息。
     */
    private void saleToPurchaseContractWirePayInfo(BamuPurchaseContract bamuPurchaseContract,
                                                   BamuContractWirePay contractWirePay) {
        // 初始化采购合同的汇款信息对象
        BamuContractWirePay purchaseContractWirePay = new BamuContractWirePay();

        // 设置采购合同ID
        purchaseContractWirePay.setContractId(bamuPurchaseContract.getId());

        // 以下多行代码将汇款信息中的各项详细数据复制到采购合同的汇款信息对象中
        purchaseContractWirePay.setPriceType(contractWirePay.getPriceType());
        purchaseContractWirePay.setPriceTypeMark(contractWirePay.getPriceTypeMark());
        purchaseContractWirePay.setBasePrice(contractWirePay.getBasePrice());
        purchaseContractWirePay.setIncreasePrice(contractWirePay.getIncreasePrice());
        purchaseContractWirePay.setIncreaseRate(contractWirePay.getIncreaseRate());
        purchaseContractWirePay.setPaymentCycle(contractWirePay.getPaymentCycle());
        purchaseContractWirePay.setPaymentReconciliationMonth(contractWirePay.getPaymentReconciliationMonth());
        purchaseContractWirePay.setPaymentReconciliationDay(contractWirePay.getPaymentReconciliationDay());
        purchaseContractWirePay.setContractPreStatus(contractWirePay.getContractPreStatus());
        purchaseContractWirePay.setOrderPreStatus(contractWirePay.getOrderPreStatus());
        purchaseContractWirePay.setTenantId(contractWirePay.getTenantId());

        // 保存采购合同的汇款信息到数据库
        iBamuContractWirePayService.save(purchaseContractWirePay);
    }


    /**
     * 将销售合同信息转换为采购合同信息
     * 此方法主要用于创建与销售合同对应的采购合同，将销售合同的相关信息
     * 复制到采购合同中，并根据销售合同类型（主合同或补充合同）进行不同的处理
     *
     * @param bamuSaleContract 销售合同对象，包含销售合同的详细信息
     * @return 返回创建的采购合同对象
     */
    private BamuPurchaseContract saleToPurchaseContractInfo(BamuSaleContract bamuSaleContract) {
        // 获取销售合同的编号、名称、ID和类型
        String saleContractNo = bamuSaleContract.getContractNo();
        String saleContractName = bamuSaleContract.getContractName();
        String saleContractId = bamuSaleContract.getId();
        String saleContractType = bamuSaleContract.getContractType();

        // 初始化采购合同对象，并设置销售合同ID、编号和名称
        BamuPurchaseContract bamuPurchaseContract = new BamuPurchaseContract();
        bamuPurchaseContract.setSaleContractId(saleContractId);
        bamuPurchaseContract.setSaleContractNo(saleContractNo);
        bamuPurchaseContract.setSaleContractName(saleContractName);

        // 根据销售合同编号生成采购合同编号
        String purchaseContractNo = saleContractNo.replace(SALE_CODE_PREFIX_SHORT,
                PURCHASE_CODE_PREFIX_SHORT);
        // 检查是否已存在对应的采购合同
        BamuPurchaseContract purchaseContract =
                iBamuPurchaseContractService.getByContractNo(purchaseContractNo);
        if (Objects.nonNull(purchaseContract)) {
            // 如果存在，则生成新的采购合同编号
            purchaseContractNo = getNewPurchaseCode(purchaseContractNo);
        }
        bamuPurchaseContract.setContractNo(purchaseContractNo);

        // 复制销售合同的基本信息到采购合同中
        bamuPurchaseContract.setContractName(saleContractName);
        bamuPurchaseContract.setPurchaseDeptId(bamuSaleContract.getSupplierDeptId());
        bamuPurchaseContract.setPurchaseDeptName(bamuSaleContract.getSupplierDeptName());
        bamuPurchaseContract.setSupplierDeptId(bamuSaleContract.getSupplierDeptId());
        bamuPurchaseContract.setSupplierDeptName(bamuSaleContract.getSupplierDeptName());
        bamuPurchaseContract.setSupplierCategoryId(bamuSaleContract.getSupplierCategoryId());
        bamuPurchaseContract.setSupplierCategoryName(bamuSaleContract.getSupplierCategoryName());
        bamuPurchaseContract.setPurchasePersonId(bamuSaleContract.getPurchasePersonId());
        bamuPurchaseContract.setPurchasePersonName(bamuSaleContract.getPurchasePersonName());
        bamuPurchaseContract.setPurchasePhone(bamuSaleContract.getPurchasePhone());
        bamuPurchaseContract.setProjectId(bamuSaleContract.getProjectId());
        bamuPurchaseContract.setProjectName(bamuSaleContract.getProjectName());
        bamuPurchaseContract.setProjectDeptId(bamuSaleContract.getProjectDeptId());
        bamuPurchaseContract.setProjectDeptName(bamuSaleContract.getProjectDeptName());
        bamuPurchaseContract.setProjectManager(bamuSaleContract.getProjectManager());
        bamuPurchaseContract.setInquiryNo(bamuSaleContract.getInquiryNo());
        bamuPurchaseContract.setProjectAddress(bamuSaleContract.getProjectAddress());
        bamuPurchaseContract.setProjectManagerId(bamuSaleContract.getProjectManagerId());
        bamuPurchaseContract.setContractNum(bamuSaleContract.getContractNum());
        bamuPurchaseContract.setDiffPricePoints(BigDecimal.ZERO);

        /*// 计算99%的百分比
        BigDecimal percentage =
                BigDecimal.ONE.subtract(bamuPurchaseContract.getDiffPricePoints().divide(new BigDecimal("100"), 2,
                        RoundingMode.HALF_UP));

        // 使用99%的百分比来更新合同总价
        BigDecimal contractTotalPriceAdjusted =
                percentage.multiply(bamuSaleContract.getContractTotalPrice());*/
        bamuPurchaseContract.setContractTotalPrice(bamuSaleContract.getContractTotalPrice());

        /*// 使用99%的百分比来更新实际合同总价
        BigDecimal contractTotalRealPriceAdjusted =
                percentage.multiply(bamuSaleContract.getContractTotalRealPrice());*/
        bamuPurchaseContract.setContractTotalRealPrice(bamuSaleContract.getContractTotalRealPrice());


        bamuPurchaseContract.setContractTotalRealPriceMark(bamuSaleContract.getContractTotalRealPriceMark());
        bamuPurchaseContract.setSignDate(bamuSaleContract.getSignDate());
        bamuPurchaseContract.setPaymentDeadlineDate(bamuSaleContract.getPaymentDeadlineDate());
        bamuPurchaseContract.setContractType(bamuSaleContract.getContractType());
        bamuPurchaseContract.setTenantId(bamuSaleContract.getTenantId());
        bamuPurchaseContract.setMark(bamuSaleContract.getMark());
        bamuPurchaseContract.setContractMethod(bamuSaleContract.getContractMethod());
        bamuPurchaseContract.setSupplyDeptId(bamuSaleContract.getSupplyDeptId());
        bamuPurchaseContract.setSupplyDeptName(bamuSaleContract.getSupplyDeptName());

        // 处理补充合同的情况，设置主合同ID和编号
        if (StringUtils.equals(saleContractType, String.valueOf(SaleContractType.SALE.getType()))) {
            String mainContractId = bamuSaleContract.getMainContractId();
            BamuPurchaseContract mainPurchaseContract =
                    iBamuPurchaseContractService.getBySaleContractId(mainContractId);
            if (Objects.isNull(mainPurchaseContract)) {
                throw new RuntimeException("补充合同审核无主合同信息");
            }
            bamuPurchaseContract.setMainContractId(mainPurchaseContract.getId());
            bamuPurchaseContract.setMainContractNo(mainPurchaseContract.getContractNo());
            bamuPurchaseContract.setMainContractName(mainPurchaseContract.getContractName());
        }

        // 保存采购合同信息
        iBamuPurchaseContractService.save(bamuPurchaseContract);

        // 处理主合同的情况，更新主合同ID和编号
        if (StringUtils.equals(saleContractType,
                String.valueOf(SaleContractType.MASTER.getType()))) {
            bamuPurchaseContract.setMainContractId(bamuPurchaseContract.getId());
            bamuPurchaseContract.setMainContractNo(bamuPurchaseContract.getContractNo());
            bamuPurchaseContract.setMainContractName(bamuPurchaseContract.getContractName());
            iBamuPurchaseContractService.updateById(bamuPurchaseContract);
        }

        // 返回采购合同对象
        return bamuPurchaseContract;
    }

    public String getNewPurchaseCode(String purchaseContractNo) {
        return purchaseContractNo + MINUS + String.format("%03d",
                RandomUtils.generateRandomThreeDigitNumber());
    }

    /**
     * 检查审批数据是否符合要求
     * 此方法主要用于校验传入的销售合同对象中的审批数据是否满足继续处理的条件
     * 如果数据不符合要求，将抛出AuditException异常，以阻止不合适的处理流程
     *
     * @param bamuSaleContract 销售合同对象，包含审批状态、流程实例ID和部署ID等信息
     * @throws AuditException 如果销售合同对象为空、审批状态不为“审核中”、流程实例ID为空或部署ID为空时抛出此异常
     */
    private void checkApprovalData(BamuSaleContract bamuSaleContract) throws AuditException {
        // 检查销售合同对象是否为空，如果为空则抛出异常，提示没有数据
        if (Objects.isNull(bamuSaleContract)) {
            throw new AuditException(ResultMsgEnum.NO_DATA);
        }
        // 获取并解析审批状态，检查是否为“审核中”状态，如果不是，则抛出异常，提示提交审批状态错误
        String auditStatus = bamuSaleContract.getAuditStatus();
        if (AuditStatusEnums.AUDIT.getType() != Integer.parseInt(auditStatus)) {
            throw new AuditException(ResultMsgEnum.SUBMIT_AUDIT_STATUS_ERROR);
        }
        // 获取流程实例ID，并检查其是否为空，如果为空则抛出异常
        String processInstanceId = bamuSaleContract.getProcessInstanceId();
        if (StringUtils.isBlank(processInstanceId)) {
            throw new AuditException("processInstanceId is null");
        }
        // 获取部署ID，并检查其是否为空，如果为空则抛出异常
        String deploymentId = bamuSaleContract.getDeploymentId();
        if (StringUtils.isBlank(deploymentId)) {
            throw new AuditException("deploymentId is null");
        }
    }

    public boolean userIsAuditButton(String schemeInfoId, String processInstanceId) {
        try {
            return isCheckAudit(schemeInfoId, processInstanceId);
        } catch (Exception e) {
            log.info("销售合同userIsAuditButton error:{}", e.getMessage());
            return false;
        }
    }

    /**
     * 检查提交的数据是否符合要求
     * 此方法主要用于验证在进行提交操作前，提供的数据是否有效和符合规定的状态
     * 它确保了数据的完整性和流程的正确性，防止了无效数据的进一步处理
     *
     * @param bamuSaleContract 待检查的销售合同对象
     * @throws AuditException 如果数据校验不通过，抛出自定义异常
     */
    private void checkSubmitData(BamuSaleContract bamuSaleContract) throws AuditException {

        // 检查传入的对象是否为空，如果为空则抛出异常，提示没有数据可以审核
        if (Objects.isNull(bamuSaleContract)) {
            throw new AuditException(ResultMsgEnum.NO_DATA);
        }

        // 获取并解析审核状态，判断是否处于不合理的审核状态
        String auditStatus = bamuSaleContract.getAuditStatus();
        // 如果审核状态处于审核中、审核成功、审核失败中的任意一种，则抛出异常，提示提交审核状态错误
        if (AuditStatusEnums.AUDIT.getType() == Integer.parseInt(auditStatus)
                || AuditStatusEnums.AUDIT_SUCCESS.getType() == Integer.parseInt(auditStatus)
//                || AuditStatusEnums.AUDIT_REJECT.getType() == Integer.parseInt(auditStatus)
        ) {
            throw new AuditException(ResultMsgEnum.SUBMIT_AUDIT_STATUS_ERROR);
        }

        // 获取并解析绑定合同状态，判断是否已经绑定合同
        String bindContractStatus = bamuSaleContract.getBindContractStatus();
        // 如果绑定合同状态为已绑定，则抛出异常，提示绑定合同状态错误
        if (BindContractStatusEnums.YES.getType() == Integer.parseInt(bindContractStatus)) {
            throw new AuditException(ResultMsgEnum.BIND_CONTRACT_STATUS_ERROR);
        }
        String id = bamuSaleContract.getId();
        BamuContractWirePay bamuContractWirePay = iBamuContractWirePayService.getByContractId(id);
        if (Objects.isNull(bamuContractWirePay)) {
            throw new AuditException("合同支付方式信息为空不可提交审核");
        }
        List<BamuContractNodePay> nodePayList = iBamuContractNodePayService.listByContractId(id);
        if (CollectionUtils.isEmpty(nodePayList)) {
            throw new AuditException("合同付款方式节点信息为空不可提交审核");
        }
        List<BamuContractMaterial> contractMaterialList = iBamuContractMaterialService.listByContractId(id);
        if (CollectionUtils.isEmpty(contractMaterialList)) {
            throw new AuditException("合同材料为空不可提交审核");
        }
    }

}
